/**
 * 树组件
 */
(function(namespace) {
	
	/**
	 * tree dom 个人觉得不怎么容易写好，容易混乱，最好理清思路
	 * 
	 */
	"use strict";

	var NO_TEXT_SELECTED = "xtree_noTextSelected",
	hasImg = "xtree_hasImg", 
	nodeCollapse = "xtree_nodeCollapse", 
	nodeExpand = "xtree_nodeExpand", 
	signImg = "xtree_signImg", 
	itemBody = "xtree_itemBody", 
	treeItem = "xtree_treeItem", 
	onselected = "xtree_onselected",
	xtree_checkbox = "xtree_checkbox",
	xtree_checkbox_checked = "xtree_checkbox_checked",
	xtree_checkbox_unchecked = "xtree_checkbox_unchecked",
	xtree_imgIcon = "xtree_imgIcon",
	xtree_body = "xtree_body";
	
	/**
	 * opt是传入的一些选项，是否有勾选框等属性
	 * opt = {
	 * hasCheckBox : true
	 * }
	 */
	function XTree(parentDom,opt,wnd) {
		this.option = opt || {};
		var option = this.option;
		this.queryUrl = this.option["queryUrl"];
		this.parentDom = parentDom;
		this.treeDiv = $("<div>").appendTo(this.parentDom).addClass(xtree_body);
		this.treeDiv[0].oncontextmenu = function(){
			return false;
		};//解除右键
		$(this.treeDiv).addClass(NO_TEXT_SELECTED);
		this.wnd = wnd || window;
		this.doc = this.wnd.document;
		this.hasCheckBox = option["hasCheckBox"] || false;
		this.selectedItems = [];
		this.rootItem = new XTreeItem(this, option["rootText"] || "根节点",this.option["rootObj"]);
	}

	/**
	 * 获取选中
	 */
	XTree.prototype.getSelectedItems = function() {
		return this.selectedItems;
	};

	/**
	 * 创建节点
	 * @param parentNode
	 * @param text
	 * @returns {XTreeItem}
	 */
	XTree.prototype.createNode = function(parentNode, text,userObj) {
		var item = new XTreeItem(parentNode, text,userObj);
		return item;
	};
	/**
	 * 设置是否有checkBox
	 * @param yes
	 */
	XTree.prototype.setCheckBox = function (yes){
		this.hasCheckBox = yes;
	};
	
	/**
	 * 设置每个节点的onCheck事件 this对象是当前节点
	 * @param func
	 */
	XTree.prototype.setOnCheck = function (func){
		this.OnCheckEvent = func;
	};
	
	XTree.prototype.setQueryUrl = function(url){
		this.queryUrl = url;
	};
	
	XTree.prototype.removeNode = function(item,callback){
		item.dispose();
		if(typeof callback =="function") callback();
	};
	
	XTree.prototype.setOnContextMenu = function(func){
		this.oncontextmenu = func;
	};
	
	XTree.prototype.setWidth = function(width){
		$(this.treeDiv).width(width);
	};
	XTree.prototype.setHeight = function(height){
		$(this.treeDiv).height(height);
	};
	/**
	 * parentNode 父节点 text 节点内容 创建根节点
	 * 第三个参数userObj是每个节点自己的供用户进行后台请求等 这里可能不好，耦合度太高了，建议传入一个opt userObj作为他的成员
	 * userObj={
	 * id:id,
	 * url:url
	 * }
	 */
	function XTreeItem(parentNode, text,opt) {
		if (parentNode instanceof XTree) {
			this.isRootItem = true;
			this.owner = parentNode;
		} else {
			this.owner = parentNode.owner;
			this.isRootItem = false;
		}
		this.opt = opt || {};
		this.wnd = parentNode.wnd || window;
		this.doc = this.wnd.document;
		this.text = text;
		if(this.opt["userObj"]){
			this.userObj = typeof this.opt["userObj"] == "string" ? JSON
					.parse(this.opt["userObj"]) : this.opt["userObj"];
		}
		this.parentNode = parentNode;
		this.childrenNodes = [];
		this.allChildrenNodes = [];
		this.isExpanded = false;
		this.isSelected = false;
		this.isChecked = false;
		this.isLoaded = false;
		this.hasCheckBox = this.owner.hasCheckBox;
		_initXTreeItemUI.apply(this);
		_initXTreeItemEvent.call(this);
		if(!this.isRootItem){
			this.parentNode.childrenNodes.push(this);
		}
		_initXTreeItemFromOption.call(this);
	}

	/**
	 * 初始化树节点 个人感觉用这样的方法外界访问不到，是不是好一些？ nodeDiv是代表整个节点，包含了子节点 bodySpan是自己节点的本身
	 * bodySpan包含了树节点的标识图标treeSignDiv和mainSpan mainSpan 是包含树的图标和文字
	 */
	function _initXTreeItemUI() {
		var self = this;
		var doc = self.doc;
		this.nodeDiv = $("<div>", doc);
		this.bodySpan = $("<span>", doc).appendTo(this.nodeDiv);
		this.treeSignDiv = $("<div>", doc).addClass(
				hasImg + " " + nodeCollapse + " " + signImg).appendTo(
				this.bodySpan);
		this.checkBox = $("<div>").css({
			display : this.hasCheckBox ? "" : "none"
		}).addClass(xtree_checkbox+" "+xtree_checkbox_unchecked).appendTo(this.bodySpan);
		this.mainSpan = $("<span>", doc).addClass(itemBody).appendTo(
				this.bodySpan);
		this.headImgDiv = $("<div>", doc).css({
			display : "inline-block"
		}).appendTo(this.mainSpan);
		this.textSpan = $("<span>", doc).text(self.text)
				.appendTo(this.mainSpan);
		this.imgIcon = $("<img>").addClass(xtree_imgIcon).css({"display":"none"}).appendTo(this.headImgDiv)
		if (this.isRootItem) {
			$(this.owner.treeDiv).append(self.nodeDiv);
		} else {
			this.nodeDiv.addClass(treeItem);
			if (!this.parentNode.isExpanded) {
				this.nodeDiv.css("display", "none");
			}
			$(this.parentNode.nodeDiv).append(self.nodeDiv);
		}

	}

	function _initXTreeItemEvent() {
		var self = this;
		var tree= self.owner;
		this.mainSpan.bind({
			"click.treeitem" : On_TreeItem_Click.bind(this),
			"dblclick.treeitem" : On_TreeItem_DbClick.bind(this),
			"mousedown.treeitem" : On_TreeItem_MouseDown.bind(this)
		});
		this.treeSignDiv
				.bind("click.treeitem", On_TreeSignDiv_Click.bind(this));
		this.checkBox.bind("click.treeitem", On_CheckBox_Click.bind(this));
	}

	function _initXTreeItemFromOption(){
		var obj = this.opt;
		var iconPath = obj["iconPath"];
		if(iconPath){
			this.setItemIconByImg(iconPath);
		}
		var hasChild = obj["hasChild"];
		if(hasChild == "false"){
			this.isLoaded = true;
			this.expandNode();
		}
	}
	/**
	 * 鼠标单击树节点事件
	 */
	function On_TreeItem_Click(evt) {
		var self = this;
		var tree = this.owner;
		var tempselected = this.isSelected;
		var isMultiselected = false;
		var selectedItems = tree.selectedItems;
		if (evt.ctrlKey) {

		} else {
			var len = selectedItems.length;
			isMultiselected = len > 1 ? true : false;
			while (len > 0) {
				var lastItem = selectedItems[len - 1];
				lastItem.setSelected(false);
				len = selectedItems.length;
			}
		}
		// 如果以前是多选，那么这次不管怎么样，都一定是被选中
		isMultiselected ? this.setSelected(true) : this
				.setSelected(!tempselected);
		if (typeof this.onClickEvent == "function")
			this.onClickEvent();
	}
	
	/**
	 * 右键事件
	 */
	function On_TreeItem_MouseDown(evt){
		if(evt.which==3){
			var tree = this.owner;
			if(typeof tree.oncontextmenu == "function"){
				tree.oncontextmenu(this);
				var selectedItems = tree.selectedItems;
				for(var i =0,len = selectedItems.length;i<len;i++){
					selectedItems[i].setSelected(false);	
				}
				this.setSelected(true);
			}
		}
	}
	/**
	 * mainSpan双击事件
	 */
	function On_TreeItem_DbClick() {
		On_TreeSignDiv_Click.call(this);
		this.setSelected(true);
	}
	/**
	 * head图片div
	 */
	function On_TreeSignDiv_Click() {
		if (this.isExpanded) {
			this.collapseNode();
		} else {
			this.expandNode();
		}
	}
	/**
	 * 执行Oncheck事件，自己的事件优先于树的事件先执行
	 */
	function On_CheckBox_Click() {
		var tree = this.owner;
		//this.isChecked = this.checkBox.is(':checked');// 为什么可以这样写呢
		if (!this.isChecked) {
			this.setChecked(true);
			if (typeof this.OnCheckEvent == "function")
				this.OnCheckEvent();
			if (typeof tree.OnCheckEvent == "function")
				tree.OnCheckEvent.bind(this)();
		}else{
			this.setChecked(false);
		}
		
	}
	/**
	 * 某个节点的触发事件
	 */
	XTreeItem.prototype.setOnClick = function(func) {
		this.onClickEvent = func;
	};

	/**
	 * 设置选中
	 */
	XTreeItem.prototype.setSelected = function(yes) {
		var tree = this.owner;
		var selectedItems = tree.selectedItems;
		var index = selectedItems.indexOf(this);
		if (yes == true) {
			this.isSelected = true;
			this.mainSpan.addClass(onselected);
			if (index === -1) {
				selectedItems.push(this);
			}
		} else {
			this.isSelected = false;
			this.mainSpan.removeClass(onselected);
			if (index !== -1) {
				selectedItems.splice(index, 1);
			}
		}
	};

	/**
	 * 注释如关闭的节点方法一样
	 * 如果树设置了queryUrl 则说明要从后台加载
	 * 这里的回调事调用有问题
	 */
	XTreeItem.prototype.expandNode = function(level, callback) {
		var self = this;
		if ((this.isExpanded || !this.parentNode.isExpanded)
				&& !this.isRootItem) {
			return;
		}
		var childrens = this.childrenNodes;
		if (!childrens.length) {
			this.treeSignDiv.removeClass(hasImg);
			var queryUrl =this.owner.queryUrl;
			if (queryUrl && !isEmptyObj(this.userObj)&&this.isLoaded==false) {
				this.isLoaded = true;
				var map = new Map;
				for ( var i in this.userObj) {
					map.put(i, this.userObj[i]);
				}
				var waitingItem = new XTreeItem(self, "正在载入");
				waitingItem.treeSignDiv.removeClass(hasImg);
				waitingItem.setHasCheckBox(false);
				this.isExpanded = false;
				self.expandNode();
				sendMsgSync(queryUrl,map,function(data){
					var obj = JSON.parse(data);
					for(var i =0 ,len =obj.length;i<len;i++){
						var text = obj[i]["text"];
						var item = new XTreeItem(self,text, obj[i]);
					}
					self.owner.removeNode(waitingItem);
					self.isExpanded=false;
					self.expandNode();
				});
			}
			return;
		}
		this.treeSignDiv.addClass(hasImg);
		for ( var i = 0, len = childrens.length; i < len; i++) {
			childrens[i].nodeDiv.css("display", "");
			if (typeof level === "number" && level > 0) {
				level--;
				childrens[i].expandNode(level, callback);
			} else if ("all" === level) {
				childrens[i].expandNode(level, callback);
			}
		}
		this.isExpanded = true;
		this.treeSignDiv.removeClass(nodeCollapse);
		this.treeSignDiv.addClass(nodeExpand);
		if (typeof callback == "function") {
			callback();
		}
	};

	/**
	 * 关闭节点 第一个参数如果为“all” 是关闭所有节点
	 * 传数字，代表关闭层数
	 * callback是每个节点展开的回调
	 */
	XTreeItem.prototype.collapseNode = function(level, callback) {
		if ((!this.isExpanded || !this.parentNode.isExpanded)
				&& !this.isRootItem)
			return;
		var childrens = this.childrenNodes;
		if (!childrens.length) {
			this.treeSignDiv.removeClass(hasImg);
			return;
		}
		for ( var i = 0, len = childrens.length; i < len; i++) {
			childrens[i].nodeDiv.css("display", "none");
			if (typeof level === "number" && level > 0) {
				level--;
				childrens[i].collapseNode(level, callback);
			} else if (level === "all") {
				childrens[i].collapseNode(level, callback);
			}
		}
		this.isExpanded = false;
		this.treeSignDiv.removeClass(nodeExpand);
		this.treeSignDiv.addClass(nodeCollapse);
		if (typeof callback == "function") {
			callback();
		}
	};
	/**
	 * 设置是否有checkBox
	 * @param yes
	 */
	XTreeItem.prototype.setHasCheckBox = function(yes){
			if(yes == true){
				this.checkBox.css("display","");
				this.hasCheckBox = true;
			}else{
				this.checkBox.css("display","none");
				this.hasCheckBox = false;
			}
	};
	/**
	 * 设置oncheck事件
	 * @param func
	 */
	XTreeItem.prototype.setOnCheck = function (func){
		this.OnCheckEvent = func;
	};
	/**
	 * 设置是否被勾选  
	 * 要用check属性
	 * @param yes
	 */
	XTreeItem.prototype.setChecked = function(yes){
		var children = this.childrenNodes;
		for(var i =0,len=children.length;i<len;i++){
			children[i].setChecked(yes);
		}
		if(yes == true){
			this.isChecked = true;
			this.checkBox.addClass(xtree_checkbox_checked);
			this.checkBox.removeClass(xtree_checkbox_unchecked);
		}else{
			this.isChecked = false;
			this.checkBox.addClass(xtree_checkbox_unchecked);
			this.checkBox.removeClass(xtree_checkbox_checked);
		}
	};
	/**
	 * 设置内容
	 * @param text
	 */
	XTreeItem.prototype.setItemText = function (text){
		this.textSpan.text(text);
	};

	/**
	 * 通过样式给它设置背景图片
	 */
	XTreeItem.prototype.setItemIconByClass = function (classes){
		this.headImgDiv.attr("class","");
		this.headImgDiv.addClass(classes);
		this.imgIcon.css("display","none");
	};
	
	/**
	 * 通过图片地址给他设置
	 * @param imgSrc
	 */
	XTreeItem.prototype.setItemIconByImg = function(imgSrc){
		this.imgIcon.attr("src",realPath+imgSrc).css("display","");
	};
	
	XTreeItem.prototype.setUserObj = function (obj) {
		this.userObj = obj;
	};
	
	XTreeItem.prototype.dispose = function(){
		this.wnd = null;
		this.doc = null;
		this.text = null;
		this.userObj = null;
		if(!this.isRootItem){
			var brothers = this.parentNode.childrenNodes;
			var index =-1;
			if((index = brothers.indexOf(this))!==-1){
				brothers.splice(index,1);
			}
		}
		this.parentNode = null;
		for(var i=0,len=this.childrenNodes.length;i<len;i++){
			this.childrenNodes[i].dispose();
		}
		this.allChildrenNodes = null;
		this.isExpanded = null;
		if(this.isSelected==true){
			var selecteds = this.owner.selectedItems;
			if((index = selecteds.indexOf(this))!==-1){
				selecteds.splice(index,1);
			}
		}
		this.owner = null;
		this.isRootItem = null;
		this.isSelected = null;
		this.isChecked = null;
		this.isLoaded = null;
		this.hasCheckBox = null;
		this.nodeDiv.remove();//可以移除所有事件和元素，保留对象，可以用$._data(dom元素非jqeury)["events"]查看确实把事件移除了
		this.nodeDiv = null;
		this.bodySpan = null;
		this.treeSignDiv = null;
		this.checkBox = null;
		this.mainSpan = null;
		this.headImgDiv = null;
		this.textSpan = null;
		this.imgIcon = null;
	};
	function isEmptyObj(obj){
		for(var i in obj){
			if(i){
				return false;
			}
		}
		return true;
	}
	
	namespace["XTree"] = XTree;
})(window);